package com.dsl.service;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.TotalHits;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import com.dsl.dao.elasticsearch.DiscussPostRepository;
import com.dsl.entity.DiscussPost;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description 搜索业务层
 * @Author dsl
 * @Date 2024/9/19 上午11:19
 * @Version 1.0
 */
@Service
public class ElasticsearchService {

    @Autowired
    private DiscussPostRepository discussPostRepository;


    //向ES中存储帖子
    public void saveDiscussPost(DiscussPost post) {
        discussPostRepository.save(post);
    }

    //在ES中删除帖子
    public void deleteDiscussPost(int id) {
        discussPostRepository.deleteById(id);
    }

    //在ES中搜索帖子
    public Map<String, Object> searchDiscussPost(String keyword, int current, int limit) throws IOException {

        //创建低级客户端
        RestClient restClient = RestClient.builder(new HttpHost("localhost", 9200)).build();
        //使用jackson映射器创建传输层
        ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
        //创建API客户端
        ElasticsearchClient client = new ElasticsearchClient(transport);


        //构建搜索条件
        Map<String, Object> res = new HashMap<>();
        SearchRequest searchRequest = SearchRequest.of(s -> s
                .index("discusspost")
                .query(q -> q
                        .multiMatch(m -> m
                                .query(keyword)
                                .fields("title", "content")
                        )
                )
                .sort(so -> so.field(f -> f.field("type").order(SortOrder.Desc)))
                .sort(so -> so.field(f -> f.field("score").order(SortOrder.Desc)))
                .sort(so -> so.field(f -> f.field("createTime").order(SortOrder.Desc)))
                //分页条件
                .from(current)
                .size(limit)
                //高亮显示
                .highlight(h -> h
                        .fields("title", f -> f)
                        .fields("content", f -> f)
                        .preTags("<em>")//高亮开始标签
                        .postTags("</em>")
                )
        );

        //执行搜索操作
        SearchResponse<DiscussPost> searchResponse = client.search(searchRequest, DiscussPost.class);

        //获取搜索结果总数
        TotalHits totalHits = searchResponse.hits().total();
        long total = totalHits.value();
        if(totalHits != null){
            long totalResults = totalHits.value();//获取总命中数
            System.out.println("Total results: " + totalResults);
        }
        //处理搜索结果
        List<DiscussPost> list = new ArrayList<>();
        for(Hit<DiscussPost> hit : searchResponse.hits().hits()){
            DiscussPost discussPost = hit.source();

            //获取高亮内容
            Map<String, List<String>> highlightFields = hit.highlight();

            //替换title和content中的高亮内容
            if (highlightFields != null && highlightFields.containsKey("title")) {
                List<String> titleHighlights = highlightFields.get("title");
                if (discussPost != null && !titleHighlights.isEmpty()) {
                    discussPost.setTitle(titleHighlights.get(0));
                }
            }
            if(highlightFields != null && highlightFields.containsKey("content")){
                List<String> contentHighlights = highlightFields.get("content");
                if (discussPost != null && !contentHighlights.isEmpty()) {
                    discussPost.setContent(contentHighlights.get(0));
                }
            }
            if(discussPost != null){
                list.add(discussPost);
            }
        }
        //输出搜索结果
        res.put("list", list);
        res.put("total", total);
        return res;
    }


}
